package com.my.core.util.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReflectionUtil {

    public static void main(String[] args) {

//        //处理数据库属性和类属性不一致的情况
//        Field[] declaredFields = tClass.getDeclaredFields();
//        List<Field> declaredFieldList = Arrays.asList(declaredFields);
//        declaredFieldList = declaredFieldList.stream()
//                .filter(x->x.getDeclaredAnnotation(TableField.class)!=null)
//                .collect(Collectors.toList());
//        Map<String, String> collect = declaredFieldList.stream().collect(
//                Collectors.toMap(x -> x.getDeclaredAnnotation(TableField.class).value(),
//                        x -> x.getName()));
//
////        -----------------------
//        //可能没有TableField 注解 所以要这样取一次验证
//        Field field = tClass.getDeclaredField(name);
//        //允许修改
//        field.setAccessible(true);
//
//        TableName name = tClass.getAnnotation(TableName.class);
//        String tableName = name.value();
    }
    /**
     * 通过反射获取对象属性值
     * @param target
     * @param fieldName
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T getValue(Object target, String fieldName) throws Exception {
        List<Field> fieldList = new ArrayList();
        addField(fieldList, target.getClass());
        for (Field field : fieldList) {
            if (field.getName().equals(fieldName)) {
                field.setAccessible(true);
                return (T) field.get(target);
            }
        }
        return null;
    }

    private static void addField(List<Field> fieldList, Class<?> clazz) {
        Field[] field = clazz.getDeclaredFields();
        fieldList.addAll(Arrays.asList(field));
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != Object.class) {
            addField(fieldList, superClass);
        }
    }


    /**
     * 调用传入的对象的set方法
     *
     * @param fieldName   属性名
     * @param obj         对象实例(XXEntity)
     * @param objectClass 类名(XXEntity.getClass())
     * @param param       设置的属性的值
     * @return
     */

    public static void setFieldValueByName(String fieldName, Object obj, Class objectClass, Object paramObj) {
        try {
            Class[] parameterTypes = new Class[1];
            Field field = objectClass.getDeclaredField(fieldName);
            parameterTypes[0] = field.getType();
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "set" + firstLetter + fieldName.substring(1);
            Method method = objectClass.getMethod(getter, parameterTypes);
            method.setAccessible(true);
            if (field.getType().equals(String.class)) {
                method.invoke(obj, paramObj);
            } else if (field.getType().equals(Integer.class) && !paramObj.equals("")) {
                String param = paramObj.toString();
                method.invoke(obj, Integer.parseInt(param));
            } else if (field.getType().equals(Date.class) && !paramObj.equals("")) {
                String param = paramObj.toString();
                System.out.println("param:" + param);
                if ((param.contains("/") && param.contains(":")) || (param.contains("-") && param.contains(":"))
                        || (param.contains("/") && param.contains(" "))
                        || (param.contains("-") && param.contains(" "))) {
                    if (appearNumber(param, ":") == 1) {
                        method.invoke(obj, sdfH1.parse(param.replaceAll("-", "/")));
                    } else if (appearNumber(param, ":") == 2) {
                        method.invoke(obj, sdfH2.parse(param.replaceAll("-", "/")));
                    } else {
                        method.invoke(obj, sdfH.parse(param.replaceAll("-", "/")));
                    }
                } else if (param.contains("-")) {
                    method.invoke(obj, sdf1.parse(param));
                } else if (param.contains("/")) {
                    method.invoke(obj, sdf2.parse(param));
                } else if (param.contains("年") && param.contains("月") && param.contains("日")) {
                    method.invoke(obj, sdf3.parse(param));
                } else if (param.contains(":")) {
                    method.invoke(obj, sdfTime.parse(param));
                } else {
                    method.invoke(obj, sdf.parse(param));
                }
            }else if (field.getType().equals(String[].class)){
//                List<String> strings = (List<String>) Arrays.asList(paramObj);
//                String[] objects = strings.toArray(new String[strings.size()]);
                method.invoke(obj,paramObj);
            }else if (field.getType().equals(Object.class)){
                method.invoke(obj,paramObj!=null?paramObj.toString():paramObj);
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace(); //
        } catch (Exception e) {
            e.printStackTrace(); //
        }
    }
    private static SimpleDateFormat sdfH = new SimpleDateFormat("yyyy/MM/dd HH");
    private static SimpleDateFormat sdfH1 = new SimpleDateFormat("yyyy/MM/dd HH:mm");
    private static SimpleDateFormat sdfH2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    private static SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
    private static SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy/MM/dd");
    private static SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy/MM/dd");
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
    private static SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy/MM/dd");
    /**
     * 获取指定字符串出现的次数
     *
     * @param srcText 源字符串
     * @param findText 要查找的字符串
     * @return
     */
    public static int appearNumber(String srcText, String findText) {
        int count = 0;
        Pattern p = Pattern.compile(findText);
        Matcher m = p.matcher(srcText);
        while (m.find()) {
            count++;
        }
        return count;
    }
}
